﻿using System.Collections.Generic;
using System.Collections.ObjectModel;

using G.Model;

namespace G.Runtime
{
    public class GamePlayers :
        KeyedCollection<string, GamePlayer>,
        HasGameSpace
    {
        public delegate void PlayersChangedHandler();
        public delegate void PlayerRemovedHandler(GamePlayer player);
        public event PlayersChangedHandler PlayersChangedEvent;
        public event PlayerRemovedHandler PlayerRemovedEvent;

        private readonly GameSpace _Game;
        private readonly GamePlayerDefs _GamePlayerDefs;

        public GamePlayers(GamePlayerDefs def, GameSpace game)
        {
            _Game = game;
            _GamePlayerDefs = def;
        }
        
        internal void Sync()
        {
            foreach (GamePlayerDef def in _GamePlayerDefs)
            {
                if (def.Name == "Nothing")
                {
                    continue;
                }
                
                GamePlayer v = new GamePlayer(def, _Game);
                if (!Contains(v.Name))
                {
                    Add(v);
                }
            }
        }

        protected override string GetKeyForItem(GamePlayer item)
        {
            return item.Name;
        }

        public GameSpace Game
        {
            get { return _Game; }
        }

        public GamePlayerDefs GamePlayerDefs
        {
            get { return _GamePlayerDefs; }
        }

        public void RemoveNotFound(ICollection<string> list)
        {
            List<string> remove = new List<string>();
            foreach (string key in list)
            {
                if (base.Contains(key))
                {
                    remove.Add(key);
                }
            }
            RemoveKeys(remove);
        }

        public new void Add(GamePlayer player)
        {
            if (player.Name == "Nothing")
            {
                return;
            }
            base.Add(player);
            Sync();
            if (PlayersChangedEvent != null)
            {
                PlayersChangedEvent();
            }
        }

        public new void Remove(GamePlayer player)
        {
            base.Remove(player);
            if (PlayersChangedEvent != null)
            {
                PlayersChangedEvent();
            }
            if (PlayerRemovedEvent != null)
            {
                PlayerRemovedEvent(player);
            }
        }

        public GamePlayer Get(string name)
        {
            GamePlayer result = null;
            foreach(GamePlayer player in this) {
                if (player.Name == name)
                {
                    result = player;
                    break;
                }
            }
            return result;
        }

        public void RemoveKeys(ICollection<string> remove)
        {
            foreach (string key in remove)
            {
                base.Remove(key);
                if (PlayersChangedEvent != null)
                {
                    PlayersChangedEvent();
                }
            }
        }

        public void DeterminePlayers()
        {
            List<GamePlayer> remove = new List<GamePlayer>();
            foreach (GamePlayer player in this)
            {
                if (!_Game.Elements.PlayerNames.Contains(player.Name))
                {
                    remove.Add(player);
                }
            }

            foreach (GamePlayer player in remove)
            {
                _Game.Controller.RemovePlayer(player);
                _Game.Players.Remove(player);
            }
        }

    }
}
